delete可以幫助我們刪除所有的object
。其用法和select
非常相近,而事實上delete
其實是delete (select ...)
的語法糖。
我們繼續使用[Day03]中定義的schema
:
type User {
required name: str;
multi followers: User;
}
type Article {
required title: str;
required author: User;
}
執行下列query生成兩個Article object
及四個User object
。
insert Article {
title:= "first article",
author:= (insert User {name:= "John"})
};
insert Article {
title:= "second article",
author:= (insert User {name:= "Jeff"})
};
for name in {"Tom", "Cathy"}
union (insert User {name:= name});
以下我將以Cathy
、John
、Tom
與Jeff
來簡單稱呼其name property
分別為「"Cathy"」、「"John"」、「"Tom"」與「"Jeff"」的User object
。
假設現在我們想刪除tom
,可以這麼寫:
delete User filter .name="Tom";
但delete
是一個很重要的操作,通常會先使用select
來確認所選到object
是否符合:
select User filter .name="Tom";
確認選擇無誤後,再將select
換成delete
。
如果是面對比較複雜的query時,會建議在with
中建立中間變數,像是:
with tom:= (select User filter .name="Tom")
select tom {name};
確認選擇無誤後,再將select
換成delete
:
with tom:= (select User filter .name="Tom")
delete tom {name};
如果我們想要刪掉所有的object
,您可能會很直覺的想要使用for-loop
。但別忘了,delete
是delete (select ...)
的語法糖,所以回想一下我們是怎麼使用select
選擇object
的呢?沒錯,直接select
就好,所以bulk delete
最快的方法是,使用select
確認選擇無誤:
select User;
select Article;
再將select
換成delete
:
delete User;
delete Article;
delete
是一個頗為複雜的主題,有可能需要針對每一個object type
,制訂不同的deletion police。Easy EdgeDB第十三章中有提到一些可能遇到的複雜情況。
deletion police
可以分為target deletion
及source deletion
兩種。
其中target deletion
有:
restrict
(預設)。delete source
。allow
。deferred restrict
。而source deletion
有:
allow
。delete target
。delete target if orphan
。我們這邊舉幾個常用的情況供大家參考。
由於on target delete restrict
是預設,所以目前User object
的schema與下面的schema其實是相同的:
type User {
required name: str;
multi followers: User {
on target delete restrict;
};
}
這個deletion police
是指當有一個User object
連接到其它User object
的multi followers link
時,這個User object
是無法被刪除的。
舉例來說,如果我們將John
與Tom
指定為Jeff
的multi followers link
:
with jeff:= (select User filter .name="Jeff"),
followers:= (select User filter .name in {"John", "Tom"})
update jeff
set {
followers:= followers
};
假設此時我們試圖delete
John
:
delete User filter .name="John";
會報錯如下:
edgedb error: ConstraintViolationError: deletion of default::User (988d4658-5248-11ef-af3f-b785e4ec0502) is prohibited by link target policy
Detail: Object is still referenced in link followers of default::User (988d46d0-5248-11ef-af3f-57711cc00e48).
因為John
仍在Jeff
的multi followers link
中。
此時如果將delete policy
改為on target delete delete source
:
type User {
required name: str;
multi followers: User {
on target delete delete source;
};
}
這個deletion police
是指當有一個User object
連接到其它User object
的multi followers link
時,如果這個User object
被刪除的話,與其連接的User object
也會被刪除。
此時我們可以刪除John
:
delete User filter .name="John";
再確認剩下哪些User object
:
select User {name, followers};
{
default::User {
name: 'Cathy',
followers: {}
},
default::User {
name: 'Tom',
followers: {}
}
}
可以發現只剩下Cathy
及Tom
。這是因為當我們刪除John
(target
)時,也會刪除Jeff
(source
)。
接著我們將delete policy
改為on source delete delete target
:
type User {
required name: str;
multi followers: User {
on source delete delete target;
};
}
並重新insert
回John
跟Jeff
:
for name in {"John", Jeff"}
union (insert User {name:= name});
並將John
與Tom
指定為Jeff
的multi followers link
:
with jeff:= (select User filter .name="Jeff"),
followers:= (select User filter .name in {"John", "Tom"})
update jeff
set {
followers:= followers
};
這個deletion police
是指當有一個User object
被刪除時,與其multi followers link
所連接的User object
也會被刪除。
此時我們可以刪除Jeff
:
delete User filter .name="Jeff";
再確認剩下哪些User object
:
select User {name, followers};
{default::User {name: 'Cathy', followers: {}}}
可以發現只剩下Cathy
。這是因為當我們刪除Jeff
(source
)時,也會刪除John
及Tom
(target
)。